Option Explicit On
Option Strict On

Imports System.Collections
Imports System.Collections.Generic
Imports NStl.SyntaxHelper.Compose
Imports nstl
Imports NUnit.Framework
Imports NStl.SyntaxHelper


Namespace nstl.test
    <TestFixture()> _
    Public Class MapTest
        Inherits IDictionaryTest
        ''' <summary>
        ''' Initialize() is called once during test execution before
        ''' test methods in this test class are executed.
        ''' </summary>
        <SetUp()> _
        Public Overrides Sub SetUp()
            MyBase.SetUp()
        End Sub


        ''' <summary>
        ''' Cleanup() is called once during test execution after
        ''' test methods in this class have executed unless the
        ''' corresponding Initialize() call threw an exception.
        ''' </summary>
        <TearDown()> _
        Public Overrides Sub TearDown()
            MyBase.TearDown()
        End Sub

        Protected Overrides Function CreateDictionary() As IDictionary(Of Integer, String)
            Return New Map(Of Integer, String)(Compare.Less(Of Integer))
        End Function

        <Test()> _
        Public Sub insert()

            'straight insert
            Dim k As New List(Of Integer)
            Dim v As New List(Of String)
            Dim m As New Map(Of Integer, String)(Compare.Less(Of Integer)())
            For i As Integer = 19 To 0 Step -1
                If m.Insert(New KeyValuePair(Of Integer, String)(i, i.ToString())).Value Then
                    k.Add(i)
                    v.Add(i.ToString())
                End If
            Next

            Algorithm.Reverse(k.Begin, k.End)
            Algorithm.Reverse(v.Begin, v.End)
            Assert.IsTrue(TestUtil.equal(m, k, v))

            'random numbers
            Dim tick As Integer = DateTime.Now.Second + DateTime.Now.Minute * 60 + DateTime.Now.Hour * 360
            Dim rnd As New Random(Convert.ToInt32(tick))

            Dim u As New List(Of KeyValuePair(Of Integer, String))
            m = New Map(Of Integer, String)(Compare.Less(Of Integer)())
            For i As Integer = 0 To 19 Step 1
                Dim r As Integer = rnd.Next(-10, 10)
                If m.Insert(New KeyValuePair(Of Integer, String)(r, r.ToString())).Value Then
                    u.Add(New KeyValuePair(Of Integer, String)(r, r.ToString()))
                End If
            Next

            'expceted key, values
            Algorithm.Sort(u.Begin, u.End, Compose.FGxHy(Compare.Less(Of Integer)(), _
                                                        [Select].FirstFromKeyValuePair(Of Integer, String)(), _
                                                        [Select].FirstFromKeyValuePair(Of Integer, String)()))

            k.Clear()
            v.Clear()

            Algorithm.Transform(u.Begin, u.End, k.AddInserter(), [Select].FirstFromKeyValuePair(Of Integer, String)())
            Algorithm.Transform(u.Begin, u.End, v.AddInserter(), [Select].SecondFromKeyValuePair(Of Integer, String)())

            Assert.IsTrue(TestUtil.equal(m, k, v))

        End Sub
        <Test()> _
        Public Sub ReverseIterators()
            Dim m As New Map(Of Integer, String)(Compare.Less(Of Integer)())
            For i As Integer = 9 To 0 Step -1
                m.Insert(New KeyValuePair(Of Integer, String)(i, i.ToString()))
            Next

            Dim vb As New List(Of Integer)

            Algorithm.Transform(m.RBegin, m.REnd, vb.AddInserter(), [Select].FirstFromKeyValuePair(Of Integer, String)())

            TestUtil.equal(vb, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
        End Sub
        <Test()> _
        Public Sub clear()
            Dim m As New Map(Of Integer, String)(Compare.Less(Of Integer)())
            For i As Integer = 9 To 0 Step -1
                m.Insert(New KeyValuePair(Of Integer, String)(i, i.ToString()))
            Next

            Assert.IsTrue(m.Count() = 10)
            Assert.IsTrue(Not m.Begin().Equals(m.End()))


            m.Clear()
            Assert.IsTrue(m.Count() = 0)
            Assert.IsTrue(m.Empty())
            Assert.IsTrue(m.Begin().Equals(m.End()))
        End Sub
        <Test()> _
        Public Sub count()
            Dim m As New Map(Of Integer, String)(Compare.Less(Of Integer)())
            For i As Integer = 9 To 0 Step -1
                m.Insert(New KeyValuePair(Of Integer, String)(i, i.ToString()))
            Next

            Assert.AreEqual(m.CountOf(2), 1)
            Assert.AreNotEqual(m.CountOf(11), 1)
            Assert.AreEqual(m.CountOf(11), 0)
        End Sub
        <Test()> _
        Public Sub equal_range()
            Dim m As New Map(Of Integer, String)(Compare.Less(Of Integer)())
            m.Insert(New KeyValuePair(Of Integer, String)(10, "10"))
            m.Insert(New KeyValuePair(Of Integer, String)(30, "30"))
            m.Insert(New KeyValuePair(Of Integer, String)(20, "20"))
            m.Insert(New KeyValuePair(Of Integer, String)(10, "10"))

            'map should contain 10/"10", 20/"20", 30/"30"

            Dim ret As Range(Of KeyValuePair(Of Integer, String), Map(Of Integer, String).Iterator) = _
                m.EqualRange(20)

            Assert.AreEqual(ret.Begin().Value.Key, 20)
            Assert.AreEqual(ret.End().Value.Key, 30)
            Assert.AreNotEqual(ret.Begin(), m.End())
        End Sub

        <Test()> _
        Public Sub [erase]()
            Dim s As New Map(Of Integer, String)(Compare.Less(Of Integer)())
            s.Insert(New KeyValuePair(Of Integer, String)(10, "10"))
            s.Insert(New KeyValuePair(Of Integer, String)(30, "30"))
            s.Insert(New KeyValuePair(Of Integer, String)(20, "20"))
            s.Insert(New KeyValuePair(Of Integer, String)(10, "10"))

            'set should contain 10/"10", 20/"20", 30/"30"

            'erase at position
            Dim pos As Map(Of Integer, String).Iterator = CType(s.Begin().Add(1), Map(Of Integer, String).Iterator)
            Assert.AreEqual(pos.Value.Key, 20)
            s.Erase(pos)
            Assert.IsTrue(TestUtil.equal(s, New Integer() {10, 30}, New String() {"10", "30"}))

            'erase a range
            s.Insert(20, "20")
            s.Insert(40, "40")
            s.Insert(30, "30")
            s.Insert(50, "50")
            Assert.IsTrue(TestUtil.equal(s, New Integer() {10, 20, 30, 40, 50}, New String() {"10", "20", "30", "40", "50"}))
            '                                              0,  1,  2,  3,  4

            pos = CType(s.Begin().Add(1), Global.NStl.Collections.Map(Of Integer, String).Iterator)
            Assert.AreEqual(pos.Value.Key, 20)
            Dim pos2 As Map(Of Integer, String).Iterator = CType(s.Begin().Add(3), Global.NStl.Collections.Map(Of Integer, String).Iterator)
            Assert.AreEqual(pos2.Value.Key, 40)
            s.Erase(pos, pos2)
            Assert.IsTrue(TestUtil.equal(s, New Integer() {10, 40, 50}, New String() {"10", "40", "50"}))

            'erase a value
            Dim count As Integer = s.Erase(40)
            Assert.IsTrue(TestUtil.equal(s, New Integer() {10, 50}, New String() {"10", "50"}))
            Assert.IsTrue(count = 1)
            count = s.Erase(100)
            Assert.IsTrue(TestUtil.equal(s, New Integer() {10, 50}, New String() {"10", "50"}))
            Assert.IsTrue(count = 0)
        End Sub
        <Test()> _
        Public Sub find()
            Dim m As New Map(Of Integer, String)(Compare.Less(Of Integer)())
            m.Insert(New KeyValuePair(Of Integer, String)(10, "10"))
            m.Insert(New KeyValuePair(Of Integer, String)(20, "20"))
            m.Insert(New KeyValuePair(Of Integer, String)(30, "30"))
            m.Insert(New KeyValuePair(Of Integer, String)(40, "40"))
            m.Insert(New KeyValuePair(Of Integer, String)(50, "50"))
            Assert.IsTrue(TestUtil.equal(m, New Integer() {10, 20, 30, 40, 50}, New String() {"10", "20", "30", "40", "50"}))

            Dim pos As Map(Of Integer, String).Iterator = m.Find(30)
            Assert.AreEqual(pos.Value.Value, "30")
            Assert.AreEqual(m.Begin().DistanceTo(pos), 2)
            Assert.AreNotEqual(pos, m.End())

            Assert.AreEqual(m(40), "40")

            Try
                Dim o As Object = m(60)
                Assert.Fail()
            Catch ex As Exception
            End Try
        End Sub

        <Test()> _
        Public Sub IndexerTest()
            Dim m As New Map(Of Integer, String)(Compare.Less(Of Integer)())
            m.Insert(New KeyValuePair(Of Integer, String)(10, "10"))
            m.Insert(New KeyValuePair(Of Integer, String)(20, "20"))
            m.Insert(New KeyValuePair(Of Integer, String)(30, "30"))
            m.Insert(New KeyValuePair(Of Integer, String)(40, "40"))
            m.Insert(New KeyValuePair(Of Integer, String)(50, "50"))


            Assert.AreEqual(m(10), "10")

            Try
                Dim u As Object = m(100)
                Assert.Fail()
            Catch ex As Exception
            End Try

            m(10) = "1010"
            Assert.AreEqual(m(10), "1010")

            m(200) = "200"
            Assert.AreEqual(m(200), "200")

            Assert.AreEqual(m.Count(), 6)

        End Sub

    End Class
End Namespace


